import {
  useEffect,
  useState,
  createContext,
  ReactNode,
  useContext,
  useMemo,
} from 'react';
import {CardWithAddress, CardModel} from '../db/models/cardModel';
import {useRegister} from './useRegister';
import {UserModel} from '../db/models/userModel';
import {IdentityModel} from '../db/models/identityModel';

interface CardListContextType {
  loading: boolean;
  unbinding: boolean;
  cards: CardWithAddress[];
  unbind: (cardNumber: string) => Promise<void>;
  getCards: () => Promise<void>;
}

const CardListContext = createContext<CardListContextType | undefined>(
  undefined,
);

export const useCardListProvider = (): CardListContextType => {
  const context = useContext(CardListContext);
  if (!context) {
    throw new Error(
      'useCardListProvider must be used within an CardListProvider',
    );
  }
  return context;
};

export function CardListProvider({
  children,
}: Readonly<{
  children: ReactNode;
}>) {
  const [loading, setLoading] = useState(false);
  const [cards, setCards] = useState<CardWithAddress[]>([]);
  const [unbinding, setUnbinding] = useState<boolean>(false);
  const {userUnregister} = useRegister();

  const getCards = async () => {
    setLoading(true);
    try {
      const cardModel = new CardModel();
      const result = await cardModel.getAllBindWithAddress();
      setCards(result);
      setLoading(false);
    } catch (error) {
      setLoading(false);
    }
  };

  const unbind = async (userName: string) => {
    try {
      setUnbinding(true);
      const userModel = new UserModel();
      const user = await userModel.getByUserName(userName);
      if (user == null) {
        throw Error('User not found.');
      }
      const identityModel = new IdentityModel();
      const identity = await identityModel.getByUid(userName);
      if (identity != null) {
        const result = await userUnregister(userName, user.passkeyName);
        if (result == null) {
          setUnbinding(false);
          return;
        }
      }

      const cardModel = new CardModel();
      await cardModel.unbind(userName);
      setUnbinding(false);
    } catch (error) {
      setUnbinding(false);
      throw error;
    }
  };

  useEffect(() => {
    getCards();
  }, []);

  const contextValue = useMemo(
    () => ({
      loading,
      unbinding,
      cards,
      getCards,
      unbind,
    }),
    [loading, unbinding, cards, getCards, unbind],
  );

  return (
    <CardListContext.Provider value={contextValue}>
      {children}
    </CardListContext.Provider>
  );
}

// export function useCardList() {
//   const [loading, setLoading] = useState(false);
//   const [cards, setCards] = useState<CardWithAddress[]>([]);
//   const [unbinding, setUnbinding] = useState<boolean>(false);

//   const {userUnregister} = useRegister();

//   const getCards = async () => {
//     setLoading(true);
//     try {
//       const cardModel = new CardModel();
//       const result = await cardModel.getAllBindWithAddress();
//       setCards(result);
//       setLoading(false);
//     } catch (error) {
//       setLoading(false);
//     }
//   };

//   const unbind = async (cardNumber: string) => {
//     try {
//       setUnbinding(true);
//       const userModel = new UserModel();
//       const user = await userModel.getByUserName(cardNumber);
//       if (user == null) {
//         throw Error('User not found.');
//       }
//       await userUnregister(cardNumber, user.passkeyName);
//       const cardModel = new CardModel();
//       await cardModel.unbind(cardNumber);
//       setUnbinding(false);
//     } catch (error) {
//       setUnbinding(false);
//       throw error;
//     }
//   };

//   useEffect(() => {
//     getCards();
//   }, []);

//   return {
//     loading,
//     cards,
//     getCards,
//     unbinding,
//     unbind,
//   };
// }
